/** \file    layered_img.h
  * \brief   Image consisting of several independently moving layers.
  * \date    2001, 2002
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/imglib/layered_img.h,v 1.1 2004/02/04 14:43:24 cscom1r4 Exp $
  */

#ifndef _layered_img_h_
#define _layered_img_h_

#include <vector>
#include "type.h"
#include "imageclass_decl.h"
#include "Arr2Dimg.h"
#include "typelib/types.h"

namespace img {

class bitmap;

///Image consisting of several independently moving layers.
class layered_img {
public:
	layered_img() {}

	enum binding {
		bind_top_left_corner,
		bind_top_right_corner,
		bind_bottom_left_corner,
		bind_bottom_right_corner
	};

	layered_img(int lcount, size_point image_size, 
		size_point preimage_area, binding b = bind_top_left_corner);
	void init(int lcount, size_point image_size, 
		size_point preimage_area, binding b = bind_top_left_corner);

	//getters&setters
	int lcount() const 
		{ return _layers.size(); }
	AImage & initial_layers_view( int n ) 
		{ return _layers[n].initial_view; }
	const AImage & initial_layers_view( int n ) const 
		{ return _layers[n].initial_view; }
	bRGB &no_value() 
		{ return _no_value; }
	const bRGB &no_value() const 
		{ return _no_value; }
	void set_interpolate( bool new_val ) 
		{ _interpolate = new_val; }
	bool interpolate() const 
		{ return _interpolate; }

	///makes current position of layers equal to initial position
	void reset_motion();

	///warps each layer
	void next_frame(const std::vector<QuadraticForm> &qf);
	///overloaded for convenience for 1-layered images
	void next_frame(const QuadraticForm &qf);

	//applies inversed transformation to each layer
	void prev_frame(const std::vector<QuadraticForm> &qf);
	void prev_frame(const QuadraticForm &qf);

	///combines all layers on the top of 'background'
	void combine_layers(AImage &background, 
		const bitmap *mask = 0, bool noNoValue = false, int_point * displ = 0);
	void combine_layers(byte_image &background, 
		const bitmap *mask = 0, bool noNoValue = false, int_point * displ = 0);
	///temporarily substitues first layer, then combines
	void combine_ext_layer(byte_image &background, const byte_image &layer,
		const bitmap *mask = 0, bool noNoValue = false, int_point * displ = 0);

private:
	///position of the top left corner of a layer in preimage-map
	int_point displacement(const size_point &layer_size) const;

private:
	struct layer_data {
		AImage		initial_view;	///< state of layers on the zeroth time step
		PntArr2f	preimage;
	};
	std::vector<layer_data> _layers;
	bRGB		_no_value;		///< color from initial layers view that should not be written in warped image
	size_point	_image_size;	///< typical images size. combine_layers() may receive images of other sizes
	int_point	_image_dspl;	///< position of the top left corner of (background) image 'places' relative to preimage-map origin
	size_point	_preimage_area; ///< dimension of the preimages, output image and layers may have other dimension
	bool		_interpolate;	///< false finds bests existing color instead of interpolating
	binding		_b;				///< initial displacement of all layers relative to background image(s)
};

} //namespace img

#endif //_layered_img_h_
